package net.sf.cldsql.dj.container;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import net.sf.cldsql.dj.container.base.DiAop;

public class DiProxy<T> implements InvocationHandler {

    private T delegate;
    private DiAop<T> aop;

    /**
     * @param delegate
     * @param proxy
     * @return
     */
    public Object bind(T delegate, DiAop<T> aop) {
        this.delegate = delegate;
        this.aop = aop;
        return Proxy.newProxyInstance(
                this.delegate.getClass().getClassLoader(), 
                this.delegate.getClass().getInterfaces(), 
                this);
    }
    /** */
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        Object result = null;
        try {
            //call before
            if (aop != null) {
                aop.before(delegate, method);
                //aop.getClass()
                //.getDeclaredMethod("before", new Class[] {Method.class})
                //.invoke(aop, new Object[] {method});
            }
            
            //call original method
            result = method.invoke(this.delegate, args);
            
            //call after
            if (aop != null) {
                aop.after(delegate, method);
                //aop.getClass()
                //.getDeclaredMethod("after", new Class[] {Method.class})
                //.invoke(aop, new Object[] {method});
            }
        } catch (Exception e) {
            //do when exception
            if (aop != null) {
                aop.error(delegate, method, e);
                //aop.getClass()
                //.getDeclaredMethod("error", new Class[] {Method.class})
                //.invoke(aop, new Object[] {method, e});
            }
        }
        return result;
    }

}
